关于npm 依赖的开源包版本控制

你有没有认认真真写过package.json 文件?

其中 package.json 里的依赖配置项是非常重要的.

"dependencies": {
"MD5": "^1.2.1",
"async": "^0.9.0",
"body-parser": "^1.9.2",
"cluster": ">= 0.7.7",
"commander": "^2.6.0",
"compression": "^1.2.0",
"config": "^1.7.0",
"connect-multiparty": "^1.2.5",
"crypto": "0.0.3",
"domain-middleware": "^0.1.0",
"express": ">= 4.0.0",
"express-domain-middleware": "^0.1.0"
}

你能看到关于版本的控制出现各种符号,我们稍后一一说明.

开发过程中有一种开发人员确实会认认真真的写依赖配置,但是往往在版本控制处写了 "*"

当你的项目版本以来配置项里出现了星号,一定要注意了.这样的控制几乎可以说等于没有,以后的维护,发布一旦 遇上高版本,可能兼容性瞬间奔溃.

虽然作为一个开源开发者对于自己的版本升级本着向下兼容的原则,但是实际上并不是这样的.

node.js 项目并不是编译一次到处执行,不同环境下都需要在各自平台编译.所以如果你给同事/同学拷贝项目的时候, 如果你们用不同的系统,都需要在各自系统上重新编译.

这时package.json 配置里的依赖可以帮助我们下载到指定版本的包.只需要下面一个命令

npm install

我们常用的npm 命令就是 install

npm install gulp --save

就像上面的命令一样,当你安装的时候带上了 –save ,npm会自动在你命令所在目录里找到 package.json 文件,并追加到依赖配置最后一样.

当我不加任何版本安装时,默认追加方式是这样的:

"gulp": "^3.8.9"

npm也可以安装时指定一个版本

npm install express@4.0.1

如果你不知道此依赖包共有哪些版本,可以通过 info 命令来查看

$ npm info md5
npm http GET https://registry.npmjs.org/md5
npm http 200 https://registry.npmjs.org/md5

{ name: 'md5',
description: 'Kohyama\'s jsMD5. See http://jsperf.com/md5-shootout. I\'ll replace this on npm with anything else.',
'dist-tags': { latest: '1.0.0' },
versions: [ '1.0.0', '1.0.1' ],
maintainers: 'coolaj86 <coolaj86@gmail.com>',
time:
{ modified: '2015-01-10T04:35:43.515Z',
created: '2011-08-27T21:25:23.732Z',
'1.0.0': '2012-05-13T00:00:30.935Z',
'1.0.1': '2012-05-13T00:00:11.449Z' },
author: 'Yoshinori Kohyama (http://jp.linkedin.com/pub/yoshinori-kohyama/36/155/9b8)',
repository:
{ type: 'git',
url: 'git://github.com/coolaj86/jsMD5.git' },
users: { haeck: true, samhou1988: true },
homepage: 'https://github.com/coolaj86/jsMD5',
keywords: [ 'ender', 'md5', 'browser' ],
readmeFilename: '',
version: '1.0.0',
main: 'index.js',
engines: { node: '*' },
dependencies: {},
devDependencies: {},
optionalDependencies: {},
dist:
{ shasum: '9f50a07f110b70e0cf38ecf4423c3b1b7e82605d',
tarball: 'http://registry.npmjs.org/md5/-/md5-1.0.0.tgz' },
directories: {}
}

关于npm 的详细信息可以单独开一篇博客来讲了,我们还是要回到 package.json 的版本控制:

"cluster": ">= 0.7.7",
"commander": "^2.6.0",
"async" : "*",

我们来看下上面这3种有何区别:

第 0 钟

即前缀什么都不写,直接写死版本号,这是最稳妥的做法,也是现在很多项目的做法:

"react": "15.3.0",

比如这个 实际的项目。

第一种

貌似通过字面意思你应该懂得, cluster 版本必须大于等于 0.7.7 npm 安装的时候你也可以这样指定:

npm install cluster@">=0.7.7"

甚至你可以把版本范围指定到更小

npm install cluster@">=0.7.7<0.8.0"

让安装的版本大于0.7.7并且小于 0.8.0

第二种

上面我们提到过默认通过包名称安装,写入package.json 里的版本控制前面就加了 ^ (上尖号) ^ 符号表示,可以接受 小版本和补丁版本的变化.什么意思?简单说就是大版本不变即可,其他版本随便更新.

"commander":"^2.6.0"

当我们npm install 的时候,安装到 nodemodules 目录下的 commander开源包可能是 2.6.0 或 2.7.3 或 2.8.9 ……只要前面2不变即可.

这种版本限制先对宽松,还是少用为妙.

如果你确定代码已经健壮,api已经非常稳定,而且开发者确实对兼容性做的很好,关键开发者还符合版本规范,这样控制版本也可行

第三种

"async": " * "

我上面说过的,最糟糕的一种版本控制,一点限制没有.

假如:

我本地使用了 async.forEach 接口,代码都测试没有问题,过了一段时间准备发布到服务器上,拷贝代码,运行 npm install 都没有问题. 但就是程序报错跑不起来. 因为 不存在 async.forEach 这个方法.(好像是变成了 async.each 方法,不太确定了) 去本地调试,确实有啊,怎么回事, 这就是典型的版本迭代更换api方法名导致的错误,叫天天不灵,叫地地不灵. 所以防患于未然,我们不要使用 " * " 来做版本控制.

也许有人说了,那我怎么知道该使用哪个版本号? 上面介绍了一种 npm info [包名称] 来查看包的所有信息 (版本都列出来了) 你需要哪个版本,去开源代码托管处查看api 说明,确定好你代码使用的版本.

如果你是一个很懒的人,当时做项目的时候,就是参考 github 上开源代码的api来实现的,那你开源直接用npm 通过 github 开源地址来安装依赖包.

npm install git://github.com/package/path.git

原文地址